﻿using System;
using System.Linq;
using FluentValidation.TestHelper;
using GiveAQuiz.Web.Membership;
using GiveAQuiz.Web.Models;
using GiveAQuiz.Web.Validation;
using Moq;
using NUnit.Framework;

namespace GiveAQuiz.Web.Tests.Validation
{
  [TestFixture]
  public class ChangePasswordValidatorTest
  {
    public Mock<IMembershipService> MockMembershipService
    {
      get;
      private set;
    }

    public ChangePasswordValidator Validator
    {
      get;
      private set;
    }

    [TestFixtureSetUp]
    public void InitializeFixture()
    {
      MockMembershipService = new Mock<IMembershipService>();
      MockMembershipService.SetupGet(m => m.MinPasswordLength).Returns(6);
      Validator = new ChangePasswordValidator(MockMembershipService.Object);
    }

    [Test]
    public void RuleFor_CurrentPassword_should_not_have_error_when_it_is_provided()
    {
      var model = new ChangePasswordViewModel() { CurrentPassword = "password" };
      Validator.ShouldNotHaveValidationErrorFor(cp => cp.CurrentPassword, model);
    }

    [Test]
    public void RuleFor_CurrentPassword_cannot_be_null()
    {
      var model = new ChangePasswordViewModel() { CurrentPassword = null };
      Validator.ShouldHaveValidationErrorFor(cp => cp.CurrentPassword, model);
    }

    [Test]
    public void RuleFor_CurrentPassword_cannot_be_empty()
    {
      var model = new ChangePasswordViewModel() { CurrentPassword = String.Empty };
      Validator.ShouldHaveValidationErrorFor(cp => cp.CurrentPassword, model);
    }

    [Test]
    public void RuleFor_CurrentPassword_cannot_be_blank()
    {
      var model = new ChangePasswordViewModel() { CurrentPassword = " " };
      Validator.ShouldHaveValidationErrorFor(cp => cp.CurrentPassword, model);
    }

    [Test]
    public void RuleFor_NewPassword_should_not_have_error_when_it_is_provided()
    {
      var model = new ChangePasswordViewModel() { NewPassword = "password" };
      Validator.ShouldNotHaveValidationErrorFor(cp => cp.NewPassword, model);
    }

    [Test]
    public void RuleFor_NewPassword_cannot_be_null()
    {
      var model = new ChangePasswordViewModel() { NewPassword = null };
      Validator.ShouldHaveValidationErrorFor(cp => cp.NewPassword, model);
    }

    [Test]
    public void RuleFor_NewPassword_cannot_be_empty()
    {
      var model = new ChangePasswordViewModel() { NewPassword = String.Empty };
      Validator.ShouldHaveValidationErrorFor(cp => cp.NewPassword, model);
    }

    [Test]
    public void RuleFor_NewPassword_cannot_be_blank()
    {
      var model = new ChangePasswordViewModel() { NewPassword = " " };
      Validator.ShouldHaveValidationErrorFor(cp => cp.NewPassword, model);
    }

    [Test]
    public void RuleFor_NewPassword_must_be_longer_than_6_characters()
    {
      var model = new ChangePasswordViewModel() { NewPassword = "12345" };
      var vr = Validator.Validate(model);
      // actually validates against the "NewPassword.Length" property
      Assert.IsNotNull(vr.Errors.FirstOrDefault(vf => vf.PropertyName.Equals("Length")));
    }

    [Test]
    public void RuleFor_NewPassword_should_not_have_error_when_6_or_more_characters()
    {
      var model = new ChangePasswordViewModel() { NewPassword = "123456" };
      var vr = Validator.Validate(model);
      // actually validates against the "NewPassword.Length" property
      Assert.IsNull(vr.Errors.FirstOrDefault(vf => vf.PropertyName.Equals("Length")));
    }

    [Test]
    public void RuleFor_RepeatPassword_should_not_have_error_when_it_is_provided()
    {
      var model = new ChangePasswordViewModel() { NewPassword = "password", RepeatPassword = "password" };
      Validator.ShouldNotHaveValidationErrorFor(cp => cp.RepeatPassword, model);
    }

    [Test]
    public void RuleFor_RepeatPassword_cannot_be_null()
    {
      var model = new ChangePasswordViewModel() { RepeatPassword = null };
      Validator.ShouldHaveValidationErrorFor(cp => cp.RepeatPassword, model);
    }

    [Test]
    public void RuleFor_RepeatPassword_cannot_be_empty()
    {
      var model = new ChangePasswordViewModel() { RepeatPassword = String.Empty };
      Validator.ShouldHaveValidationErrorFor(cp => cp.RepeatPassword, model);
    }

    [Test]
    public void RuleFor_RepeatPassword_cannot_be_blank()
    {
      var model = new ChangePasswordViewModel() { RepeatPassword = " " };
      Validator.ShouldHaveValidationErrorFor(cp => cp.RepeatPassword, model);
    }

    [Test]
    public void RuleFor_RepeatPassword_must_be_longer_than_6_characters()
    {
      var model = new ChangePasswordViewModel() { RepeatPassword = "12345" };
      var vr = Validator.Validate(model);
      // actually validates against the "RepeatPassword.Length" property
      Assert.IsNotNull(vr.Errors.FirstOrDefault(vf => vf.PropertyName.Equals("Length")));
    }

    [Test]
    public void RuleFor_RepeatPassword_should_not_have_error_when_6_or_more_characters()
    {
      var model = new ChangePasswordViewModel() { NewPassword ="123456", RepeatPassword = "123456" };
      var vr = Validator.Validate(model);
      // actually validates against the "RepeatPassword.Length" property
      Assert.IsNull(vr.Errors.FirstOrDefault(vf => vf.PropertyName.Equals("Length")));
    }

    [Test]
    public void RuleFor_RepeatPassword_must_match_NewPassword()
    {
      var model = new ChangePasswordViewModel() { NewPassword = "password", RepeatPassword = "wrongPassword" };
      Validator.ShouldHaveValidationErrorFor(cp => cp.RepeatPassword, model);      
    }
  }
}
